﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Xml;
using System.Windows.Media;
using System.Windows;
using System.Windows.Documents;
using System.IO;
using System.Windows.Input;
using SHomeWorkshop.LunarConcept.Tools;
using System.Windows.Controls.Ribbon;
using System.Windows.Media.Imaging;

namespace SHomeWorkshop.LunarConcept
{
    /// <summary>
    /// 创建时间：2011年12月28日
    /// 创建者：  杨震宇
    /// 
    /// 主要用途：为“最近文件列表”提供列表项目。
    /// </summary>
    public class RecentFileItem : RibbonApplicationMenuItem
    {

        #region 构造方法=====================================================================================================

        /// <summary>
        /// [构造方法]生成一个RibbonApplicationMenuItem对象。
        /// </summary>
        /// <param name="fullPathFileName">指“最近文档列表”中记录的某个曾经使用的文档的全路径字符串。</param>
        public RecentFileItem(string fullPathFileName)
            : base()
        {
            this.FullPathFileName = fullPathFileName;

            string upCaseFullPathFileName = fullPathFileName.ToUpper();
            if (upCaseFullPathFileName.EndsWith(Globals.ExtensionName.ToUpper()))
            {
                this.ImageSource = docIconSource;
            }
            else if (upCaseFullPathFileName.EndsWith(Globals.ExtensionNameOfOutportPng.ToUpper()))
            {
                this.ImageSource = pngIconSource;
            }
            else if (upCaseFullPathFileName.EndsWith(Globals.ExtensionNameOfTemplate.ToUpper()))
            {
                this.ImageSource = templateIconSource;
            }

            this.Click += new RoutedEventHandler(RecentFileItem_Click);
        }

        #endregion


        #region 字段与属性===================================================================================================

        private string fullPathFileName;
        /// <summary>
        /// [读写]曾经使用的某文件的完全路径字符串。
        /// </summary>
        public string FullPathFileName
        {
            get { return fullPathFileName; }
            set
            {
                fullPathFileName = value;
                this.Header = this.ShortFileName.Replace("_", "__");//防止把文件名中的下划线字符当成界面助记键提示符。
                this.ToolTip = fullPathFileName;
            }
        }

        /// <summary>
        /// “最近文档列表”使用的图标。
        /// </summary>
        private static BitmapImage docIconSource =
            new BitmapImage(new Uri("pack://Application:,,,/LunarConcept;component/Images/LunarConcept_Document.png"));

        private static BitmapImage pngIconSource =
            new BitmapImage(new Uri("pack://Application:,,,/LunarConcept;component/Images/PictureBox.png"));

        private static BitmapImage templateIconSource =
            new BitmapImage(new Uri("pack://Application:,,,/LunarConcept;component/Images/LunarConceptTemplate.png"));

        /// <summary>
        /// [只读]从完整文件路径返回文件短名。
        /// </summary>
        public string ShortFileName
        {
            get
            {
                if (fullPathFileName == null) return null;

                if (fullPathFileName.Length <= 0) return null;

                int index = fullPathFileName.LastIndexOf('\\');

                if (index < 0)
                {
                    return fullPathFileName;
                }
                else
                {
                    return fullPathFileName.Substring(index + 1);
                }
            }
        }

        #endregion

        #region 方法=========================================================================================================

        /// <summary>
        /// [静态方法]打开指定的文档，并更新“最近文档列表”。
        /// </summary>
        /// <param name="filename">要打开的文档的全路径。</param>
        private static void OpenDocument(string filename)
        {
            Globals.MainWindow.EditorManager.CloseDocument();//“关闭”文档，其实是重置文档默认属性。

            string lowerFilename = filename.ToLower();

            if (lowerFilename.EndsWith(".lcpt"))
            {
                Commands.OpenDocumentCommand.Execute(filename);

                RecentFileItem.WriteRecentFilesToXmlFile(filename);
                RecentFileItem.ReadRecentFilesFromXmlFile();
            }
            else if (lowerFilename.EndsWith(".png") || lowerFilename.EndsWith(".lctmp"))
            {
                string result = Commands.OpenDocumentCommand.ReadOutportedPNGImageFile(filename);
                if (result == string.Empty)
                {
                    Globals.MainWindow.EditorManager.FullPathOfDiskFile = filename;
                }
                RecentFileItem.WriteRecentFilesToXmlFile(filename);
                RecentFileItem.ReadRecentFilesFromXmlFile();
            }
            else
            {
                MessageBox.Show("　　不支持这种类型的文件！请检查文件后缀名，并确定此文件是由《" + Globals.AppFormatedName + "》生成的。",
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
        }

        /// <summary>
        /// [静态方法]从磁盘文件中重新读取并刷新“最近文档列表”。
        /// </summary>
        public static void ReadRecentFilesFromXmlFile()
        {
            try
            {
                string xmlFilePath = Globals.PathOfRecentlyFiles;

                XmlDocument xDoc;

                if (File.Exists(xmlFilePath) == false)
                {
                    xDoc = XmlTools.SaveToXmlFile(xmlFilePath, Properties.Resources.RecentFilesXml);
                }
                else
                {
                    xDoc = XmlTools.LoadXmlFile(xmlFilePath);
                }

                Globals.MainWindow.RecentFileList.Items.Clear();

                if (xDoc.DocumentElement == null || xDoc.DocumentElement.Name != "RecentFiles")
                {
                    Globals.MainWindow.RecentFileList.Items.Add(
                        new TextBlock() { Text = "..最近文件列表文件格式错误.." }
                        );
                    return;
                }

                XmlNodeList nodes = xDoc.DocumentElement.SelectNodes("FullPathFileName");

                if (nodes.Count <= 0)
                {
                    Globals.MainWindow.RecentFileList.Items.Add(
                        new TextBlock() { Text = "..尚无最近文件列表.." }
                        );
                    return;
                }

                foreach (XmlNode node in nodes)
                {
                    if (node.InnerText.ToLower().EndsWith(".lcpt") ||
                        node.InnerText.ToLower().EndsWith(".lctmp") ||
                        node.InnerText.ToLower().EndsWith(".png"))
                    {
                        RecentFileItem rfi = new RecentFileItem(node.InnerText);
                        Globals.MainWindow.RecentFileList.Items.Add(rfi);
                    }//只应该读取三种后缀名。否则容易引起意外错误。
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
            }
        }

        /// <summary>
        /// 点击菜单，打开记录的路径指向的文档（如果存在）。
        /// </summary>
        void RecentFileItem_Click(object sender, RoutedEventArgs e)
        {
            //打开文档。
            if (File.Exists((sender as RecentFileItem).fullPathFileName) == false)
            {
                MessageBoxResult mbr = MessageBox.Show("　　此文件已不在原磁盘位置。要删除此条目吗？",
                    Globals.AppName, MessageBoxButton.YesNo, MessageBoxImage.Warning);

                if (mbr == MessageBoxResult.Yes)
                {
                    try
                    {
                        XmlDocument xDoc = XmlTools.LoadXmlFile(Globals.PathOfRecentlyFiles);

                        if (xDoc == null || xDoc.DocumentElement == null) return;
                        XmlNodeList nodes = xDoc.DocumentElement.SelectNodes("FullPathFileName");
                        if (nodes == null || nodes.Count <= 0) return;

                        for (int i = nodes.Count - 1; i >= 0; i--)
                        {
                            XmlNode node = nodes[i];
                            if (node.InnerText == (sender as RecentFileItem).FullPathFileName)
                            {
                                xDoc.DocumentElement.RemoveChild(node);
                            }
                        }

                        xDoc.Save(Globals.PathOfRecentlyFiles);
                        RecentFileItem.ReadRecentFilesFromXmlFile();
                        return;
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                        return;
                    }
                }
                else if (mbr == MessageBoxResult.No) return;
            }

            KeyStates ksLeft = Keyboard.GetKeyStates(Key.LeftShift);
            KeyStates ksRight = Keyboard.GetKeyStates(Key.RightShift);

            bool isShift = false;

            if ((ksLeft & KeyStates.Down) > 0 || (ksRight & KeyStates.Down) > 0)
            {
                isShift = true;
            }

            if (isShift)
            {
                System.Diagnostics.Process newProcess = System.Diagnostics.Process.Start(Globals.FullPathOfApp,
                     "\"" + (sender as RecentFileItem).fullPathFileName + "\"");
                //前后不加引号，会导致带空格的路径无法解析。

                e.Handled = true;
                return;
            }
            else
            {
                if (Globals.MainWindow.EditorManager.IsModified)
                {
                    MessageBoxResult mr = MessageBox.Show("　　当前文档已被修改，要保存吗？", Globals.AppName,
                        MessageBoxButton.YesNoCancel, MessageBoxImage.Warning, MessageBoxResult.Yes);

                    switch (mr)
                    {
                        case MessageBoxResult.Yes:
                            {
                                string saveResult = Commands.SaveDocumentCommand.Execute();

                                if (saveResult == Commands.SaveDocumentCommand.CancelSaveMessage)
                                {
                                    return;
                                }
                                if (saveResult == string.Empty)
                                {
                                    OpenDocument(fullPathFileName);
                                }
                                else
                                {
                                    MessageBox.Show("　　未能保存当前文档，异常信息如下\r\n" + saveResult, Globals.AppName,
                                        MessageBoxButton.OK, MessageBoxImage.Warning);
                                    return;
                                }

                                break;
                            }
                        case MessageBoxResult.No:
                            {
                                OpenDocument(fullPathFileName);
                                break;
                            }
                        default:
                            {
                                return;//其余都作Cancel看待。
                            }
                    }
                }
                else
                {
                    OpenDocument(fullPathFileName);
                }
            }
        }

        /// <summary>
        /// [静态方法]将“最近文档列表”数据写入磁盘配置文件中（一个Xml文档）。
        /// </summary>
        /// <param name="newFullPathFilename">此路径应传入Globals.PathOfRecentlyFiles。</param>
        public static void WriteRecentFilesToXmlFile(string newFullPathFilename)
        {
            if (Directory.Exists(Globals.PathOfUserDirectory) == false)
            {
                Directory.CreateDirectory(Globals.PathOfUserDirectory);
            }

            if (Directory.Exists(Globals.PathOfUserDirectory) == false)
            {
                MessageBox.Show("　　未能创建用户目录，不能写入“最近使用的文档列表”到磁盘。",
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            if (newFullPathFilename == null || newFullPathFilename.Length <= 0)
            {
                MessageBox.Show("　　不能将空文件路径写入“最近使用的文档列表”到磁盘。",
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            if (newFullPathFilename.ToLower().EndsWith("." + Globals.ExtensionName) == false &&
                newFullPathFilename.ToLower().EndsWith("." + Globals.ExtensionNameOfTemplate) == false &&
                newFullPathFilename.ToLower().EndsWith("." + Globals.ExtensionNameOfOutportPng) == false)
            {
                return;//只有这三种后缀名才会记载。避免意外错误。
            }

            try
            {
                XmlDocument xDoc = XmlTools.LoadXmlFile(Globals.PathOfRecentlyFiles);

                if (xDoc == null)
                {
                    xDoc = new XmlDocument();
                    xDoc.LoadXml(Properties.Resources.RecentFilesXml);
                }

                if (xDoc == null)
                {
                    MessageBox.Show("　　未找到“最近使用的文档列表”文档，且未能创建。",
                       Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                if (xDoc.DocumentElement == null)
                {
                    xDoc.CreateElement("RecentFiles");
                }

                if (xDoc.DocumentElement == null)
                {
                    MessageBox.Show("　　未找到“最近使用的文档列表”文档根节点，且未能创建。",
                       Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                XmlNodeList nodes = xDoc.DocumentElement.SelectNodes("FullPathFileName");

                if (nodes.Count <= 0)
                {
                    xDoc.DocumentElement.InnerXml = "<FullPathFileName>" + newFullPathFilename + "</FullPathFileName>";
                    xDoc.Save(Globals.PathOfRecentlyFiles);
                    return;
                }
                else
                {
                    for (int i = nodes.Count - 1; i >= 0; i--)
                    {
                        XmlNode node = nodes[i];
                        if (node.InnerText == newFullPathFilename)
                        {
                            xDoc.DocumentElement.RemoveChild(node);
                            break;
                        }
                    }

                    xDoc.DocumentElement.InsertXmlAt("<FullPathFileName>" + newFullPathFilename + "</FullPathFileName>", 0);

                    //如果超过１０个，自动删除末尾的项目。
                    XmlNodeList newNodesAfterInserted = xDoc.DocumentElement.SelectNodes("FullPathFileName");
                    if (newNodesAfterInserted.Count > 10)
                    {
                        for (int i = newNodesAfterInserted.Count - 1; i >= 10; i--)
                        {
                            xDoc.DocumentElement.RemoveChild(newNodesAfterInserted[i]);
                        }
                    }

                    xDoc.Save(Globals.PathOfRecentlyFiles);
                    return;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
        }

        #endregion
    }
}
